﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Galaktika.BI.Runtime.Services;
using Ranet.AgOlap.Core.MetadataDescription;
using Galaktika.BI.Silverlight.Controls.General.Tree;
using System.Threading;
using Galaktika.BI.Silverlight.Controls.General;
using Galaktika.BI.Silverlight.Commands;

namespace Galaktika.BI.Silverlight.Controls.MeasureChoice
{
    public partial class MeasureChoiceControl : UserControl
    {
        public MeasureChoiceControl()
        {
            InitializeComponent();
        }

        public IBindingContext Context { get; set; }

        #region Свойства для настройки на OLAP
        /// <summary>
        /// 
        /// </summary>
        private String m_Connection = String.Empty;
        /// <summary>
        /// 
        /// </summary>
        public String Connection
        {
            get
            {
                return m_Connection;
            }
            set 
            {
                m_Connection = value;
            }
        }

        /// <summary>
        /// Имя OLAP куба
        /// </summary>
        String m_CubeName = String.Empty;
        /// <summary>
        /// Имя OLAP куба
        /// </summary>
        public String CubeName
        {
            get
            {
                return this.m_CubeName;
            }
            set
            {
                m_CubeName = value;
            }
        }
        #endregion Свойства для настройки на OLAP

        private MeasureInfo m_SelectedInfo = null;
        public MeasureInfo SelectedInfo
        {
            get {
                return m_SelectedInfo;
            }
        }

        public void Initialize()
        {
            RefreshTree();
        }

        private void RefreshTree()
        {
            Tree.Items.Clear();
            m_GroupNodes.Clear();

            // Добавляем узел Measures
            FolderTreeNode measuresNode = new FolderTreeNode();
            measuresNode.Text = "Measures";
            Tree.Items.Add(measuresNode);
            measuresNode.ExpandedIcon = UriResources.Images.Measure16;
            measuresNode.CollapsedIcon = UriResources.Images.Measure16;

            measuresNode.IsExpanded = true;

            IUserTaskManager taskManager = (IUserTaskManager)Context.Services.GetService(typeof(IUserTaskManager));
            if (taskManager != null)
            {
                InvokeSchema schema = CommandBuilder.CreateGetMeasuresSchema((string)this.Context.UserData["_$Id"], m_Connection, m_CubeName);
                measuresNode.IsWaiting = true;

                taskManager.ProcessTaskItem(Localization.AppTask_DownloadingMeasures,
                    new WaitCallback(GetMeasures), 
                    new ChoiceControlInvokeSchemaWrapper(schema, measuresNode));
            }
        }

        private void GetMeasures(object state)
        {
            ChoiceControlInvokeSchemaWrapper wrapper = state as ChoiceControlInvokeSchemaWrapper;
            if (wrapper != null)
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(InvokeCommand), wrapper);
            }
        }

        void InvokeCommand(object state)
        {
            ChoiceControlInvokeSchemaWrapper wrapper = state as ChoiceControlInvokeSchemaWrapper;
            if (wrapper != null)
            {
                InvokeSchema schema = wrapper.Schema;
                using (SyncDataService ds = new SyncDataService())
                {
                    InvokeResultSchema res = ds.InvokeCommand(schema);

                    if (wrapper.UserState != null)
                    {
                        this.Dispatcher.BeginInvoke(delegate { StopWaiting(wrapper.UserState as CustomTreeNode); });
                    }

                    if (ds.Error != null)
                    {
                        LogException(ds.Error);
                        return;
                    }

                    this.Dispatcher.BeginInvoke(delegate { GetMeasures_InvokeCommandCompleted(res, wrapper.UserState as CustomTreeNode); });
                }
            }
        }

        void StopWaiting(CustomTreeNode parentNode)
        {
            if (parentNode != null)
            {
                parentNode.IsWaiting = false;
            }
        }

        void GetMeasures_InvokeCommandCompleted(InvokeResultSchema res, CustomTreeNode parentNode)
        {
            List<MeasureInfo> measures = XmlUtility.XmlStr2Obj<List<MeasureInfo>>(res.Content);
            if (measures != null)
            {
                foreach (MeasureInfo info in measures)
                {
                    CustomTreeNode groupNode = null;
                    String groupName = String.Empty;
                    //Показатели могут быть сгруппированы в группы
                    PropertyInfo pi = info.GetProperty("MEASUREGROUP_NAME");
                    if (pi != null && pi.Value != null)
                    {
                        groupName = pi.Value.ToString();
                    }
                    // Создаем узел для группы
                    if (!String.IsNullOrEmpty(groupName))
                    {
                        if (m_GroupNodes.ContainsKey(groupName))
                        {
                            groupNode = m_GroupNodes[groupName];
                        }
                        else
                        {
                            groupNode = new FolderTreeNode();
                            groupNode.Text = groupName;
                            m_GroupNodes[groupName] = groupNode;

                            if (parentNode == null)
                                Tree.Items.Add(groupNode);
                            else
                                parentNode.Items.Add(groupNode);
                        }
                    }

                    if (groupNode == null)
                        groupNode = parentNode;

                    MeasureTreeNode node = new MeasureTreeNode(info);
                    // Показатели будут конечными узлами. Двойной клик на них будет равнозначен выбору
                    node.Expanded += new RoutedEventHandler(node_Expanded);
                    node.Collapsed += new RoutedEventHandler(node_Collapsed);

                    if (groupNode == null)
                        Tree.Items.Add(node);
                    else
                        groupNode.Items.Add(node);

                }
            }
        }

        Dictionary<String, CustomTreeNode> m_GroupNodes = new Dictionary<String, CustomTreeNode>();

        private bool LogException(Exception ex)
        {
            IOutputService log = (IOutputService)Context.Services.GetService(typeof(IOutputService));
            if (log != null)
            {
                log.WriteException(ex);
                return true;
            }
            return false;
        }

        void node_Collapsed(object sender, RoutedEventArgs e)
        {
            ApplyItemsSelection();
            Raise_ApplySelection();
        }

        void node_Expanded(object sender, RoutedEventArgs e)
        {
            ApplyItemsSelection();
            Raise_ApplySelection();
        }

        /// <summary>
        /// Событие генерируется после окончания выбора
        /// </summary>
        public event EventHandler ApplySelection;

        /// <summary>
        /// Событие генерируется при нажатии на кнопку Отмена
        /// </summary>
        public event EventHandler CancelSelection;

        /// <summary>
        /// Генерирует событие "Выбор окончен"
        /// </summary>
        private void Raise_ApplySelection()
        {
            EventHandler handler = ApplySelection;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }

        /// <summary>
        /// Генерирует событие "Отмена"
        /// </summary>
        private void Raise_CancelSelection()
        {
            EventHandler handler = CancelSelection;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }

        private void OkButton_Click(object sender, RoutedEventArgs e)
        {
            ApplyItemsSelection();
            Raise_ApplySelection();
        }

        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
            // Генерируем событие - Отмена
            Raise_CancelSelection();
        }

        private void ApplyItemsSelection()
        {
            MeasureTreeNode node = null;
            node = Tree.SelectedItem as MeasureTreeNode;

            if (node != null)
            {
                //Запоминаем выбранный элемент
                m_SelectedInfo = node.Info;
            }
        }
    }
}
